﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

using Seven.Tools;
using Seven.Tools.Extension;
using Seven.Tools.Collections.Concurrent;

namespace Seven.Pool.SignalR
{
    public class MemberTokenCollection : ObservableConcurrentDictionary<Guid, MemberToken>
    {
        private object _locker = new object();

        #region 外部方法定义

        internal void Add(MemberToken token)
        {
            Check.NotNull(token);
            this.Add(token.Guid, token);
        }

        internal new void Add(Guid key, MemberToken token)
        {
            Check.NotNull(token);
            Check.Equals(key, token.Guid);
            base.Add(key, token);
        }

        internal void RemoveByUserName(string userName, string groupName)
        {
            string temp = userName != null ? userName.Trim() : string.Empty;
            Check.NotEmpty(temp);

            MemberToken[] tokens = this.GetTokenByUserName(temp, groupName);
            IEnumerable<Guid> keys = tokens.Select(s => s.Guid);
            this.TryRemoveRange(keys);
        }

        internal void RemoveByGuid(string key)
        {
            string temp = key != null ? key.Trim() : string.Empty;
            Check.NotEmpty(temp);

            Guid gkey = Guid.Empty;
            if (Guid.TryParse(temp, out gkey))
            {
                this.RemoveByGuid(gkey);
            }
        }

        internal void RemoveByGuid(Guid key)
        {
            MemberToken token = this.GetTokenByGuid(key);
            this.Remove(token);
        }

        internal void Remove(MemberToken token)
        {
            if (token == null) { return; }
            this.Remove(token.Guid);
        }

        /// <summary>
        /// 获取在指定的 <see cref="groupName"/> 中指定的 <see cref="userName"/> 的所有连接身份信息。
        /// <para>如果该方法返回一个空数组，则说明该用户无效或者尚未连接。</para>
        /// </summary>
        /// <param name="userName">用户名</param>
        /// <param name="groupName">分组名</param>
        /// <returns></returns>
        internal MemberToken[] GetTokenByUserName(string userName, string groupName)
        {
            string temp = userName != null ? userName.Trim() : string.Empty;
            Check.NotEmpty(temp);

            lock (this._locker)
            {
                return this.Values.Where(w => w.UserName == temp && w.GroupName == groupName).ToArray();
            }
        }

        /// <summary>
        /// 根据指定的连接身份信息的Token标识获取该Token标识的连接身份信息。
        /// <para>如果该方法返回 null，则说明该 <paramref name="key"/> 标识无效。</para>
        /// </summary>
        /// <param name="key">字符串格式的连接身份信息的Token标识</param>
        /// <returns></returns>
        internal MemberToken GetTokenByGuid(string key)
        {
            string temp = key != null ? key.Trim() : string.Empty;
            Check.NotEmpty(temp);

            Guid gkey = Guid.Empty;
            if (Guid.TryParse(temp, out gkey))
            {
                return this.GetTokenByGuid(gkey);
            }
            else { return null; }
        }

        /// <summary>
        /// 根据指定的连接身份信息的Token标识获取该Token标识的连接身份信息。
        /// <para>如果该方法返回 null，则说明该 <paramref name="key"/> 无效。</para>
        /// </summary>
        /// <param name="key">连接身份信息的Token标识</param>
        /// <returns></returns>
        internal MemberToken GetTokenByGuid(Guid key)
        {
            return this.GetValue(key);
        }

        /// <summary>
        /// 根据指定的用户池中的身份token标识获取该token标识在连接池中对应的连接身份信息。
        /// <para>如果该方法返回 null，则说明该 <paramref name="key"/> 无效 或 对应的用户尚未连接。</para>
        /// </summary>
        /// <param name="key">用户池中的身份token标识</param>
        /// <returns></returns>
        internal MemberToken GetTokenByUserPoolGuid(Guid key)
        {
            return this.Values.FirstOrDefault(f => f.UserPoolGuid == key);
        }

        /// <summary>
        /// 获取在连接池中的所有连接身份信息。
        /// </summary>
        /// <returns></returns>
        internal MemberToken[] GetAllToken()
        {
            return this.Values.ToArray();
        }

        #endregion
    }
}